package gnss

import (
	"dgo/goutils/utils"
	"encoding/binary"
)

type HemiObsPacket struct {
	/* Bits 0-11 (12 bits) =SNR_value
	   For All signals except GPS L2, SNR = 10.0*log10( 0.1024*SNR_value)
	   For GPS L2, SNR = 10.0*log10( 0.1164*SNR_value) */
	/* Bits 12-14 (3 bits) = 3 bits of warning
	   for potential 1/2 cycle slips.  A warning
	   exists if any of these bits are set. */
	/* bit 15: (1 bit) 1 if Track Time > 25.5 sec,
	   0 otherwise */
	/* Bits 16-23 (8 bits): Track Time in units
	   of 1/10 second (range = 0 to 25.5 seconds) */
	/* Bits 24-31 (8 bits) = Cycle Slip Counter
	   Increments by 1 every cycle slip
	   with natural roll-over after 255 */
	CS_TT_W3_SNR uint32

	/* Bit 0: (1 bit) 1 if Valid Phase, 0 otherwise
	   Bit 1-23: (23 bits) =Magnitude of doppler
	       LSB = 1/512 cycle/sec
	       Range = 0 to 16384 cycle/sec
	   Bit 24: sign of doppler, 1=negative, 0=pos
	   Bits 25-31 (7 bits) = upper 7 bits of the
	       23 bit carrier phase.
	       LSB = 64 cycles,  MSB = 4096 cycles */
	P7_Doppler_FL uint32

	/* Bit 0-15 (16 bits) lower 16 bits of code
	       pseudorange
	       LSB = 1/256 meters
	       MSB = 128 meters
	       Note, the upper 19 bits are given in
	       m_aulCACodeMSBsPRN[] for CA code
	   Bit 16-31 lower 16 bits of the carrier phase,
	             7 more bits are in m_ulP7_Doppler_FL
	       LSB = 1/1024 cycles
	       MSB = 32 cycles */
	CodeAndPhase uint32
}

/*
*
伪距的低16位
*/
func (this *HemiObsPacket) GetPsRng() float64 {
	v := this.CodeAndPhase << 16 >> 16
	return float64(v) / 256
}

/*
**

	载波
*/
func (this *HemiObsPacket) GetPhRng() float64 {
	u0 := this.P7_Doppler_FL >> 25
	v := this.CodeAndPhase >> 16
	return float64(u0)*64 + float64(v)/1024
}

/*
**

	SNR
*/
func (this *HemiObsPacket) GetRawSNR() float64 {
	v := this.CS_TT_W3_SNR << 20 >> 20
	return float64(v)
}

func (this *HemiObsPacket) GetDoppler() float64 {
	v := this.P7_Doppler_FL
	v = v << 8
	v = v >> 9
	mask := U32_1 << 24
	rval := float64(v) / 512
	if this.P7_Doppler_FL&mask > 0 {
		rval *= -1
	}
	return rval
}

func (this *HemiObsPacket) GetTrackTime() float64 {
	v := float64(0)
	bit1 := utils.GetBitV_U32(this.CS_TT_W3_SNR, 15)
	if bit1 == 1 {
		v = 25.5
	} else {
		v = 0
	}
	v1 := utils.GetU64BitsU_L(uint64(this.CS_TT_W3_SNR), 16, 8)
	v2 := float64(v) + float64(v1)*0.1
	return float64(v2)
}

func (this *HemiObsPacket) Decode(buf []byte) {
	byteN := 0

	this.CS_TT_W3_SNR = binary.LittleEndian.Uint32(buf[byteN:])
	byteN += 4

	this.P7_Doppler_FL = binary.LittleEndian.Uint32(buf[byteN:])
	byteN += 4

	this.CodeAndPhase = binary.LittleEndian.Uint32(buf[byteN:])
}
